﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
using Open_MUD.Kernel.Utils;
using Open_MUD.Mudlib.lib.Interactive;
using System.IO;
using Open_MUD.Kernel.Interface.Client.Wizards;
using System.Xml;
using Open_MUD.Mudlib.lib;
using Open_MUD.Kernel;
using OpenMUD.Kernel.Interface.Client;
using OpenMUD.Mudlib.Cmds;
using Open_MUD.Mudlib.lib.Loc;
using Open_MUD.Mudlib.Cmds;

namespace Open_MUD.Kernel.Interface.Client
{
    class Cliente : CommandExecuter
    {
        private static object objlock = new object();
        private static ArrayList clientes = new ArrayList();
        private Jugador pj = null ;
        private Interactivo controlando;
        private ArrayList historial = new ArrayList();
        private string prompt = ">";
        

        private WizardBase actualWiz = null;

        public Jugador PJ
        {
            get { return pj;}
        }        

        protected virtual string leerLinea()
        {
            return "";
        }

        protected virtual void finbucle()
        {
            return;
        }

        public virtual void doprompt(String prompt)
        {
            return ;
        }

        public virtual String render(String msg)
        {
           //TODO: Añadir scripting, por ejemplo, 
           // <pj>Smaug</pj> llega del este.
           // renderizarlo como: Smaug llega del este. Siendo Smaug en rojo por ser enemigo 
            return msg;
        }

        public void resetWizard()
        {
            actualWiz = null;
        }

        public void loadPJ(String strpj)
        {
            if (pj == null)
            {
                pj = new Jugador();
                pj.loadPJ(strpj);
                pj.Cliente = this;  
                
                load_cmds();                
                load_alias();
                 
                string id_mapa = "westeros";
                int pjx = 0;
                int pjy = 0;                
            }            
        }
        
        private void load_cmds()
        {
           register(new Ficha(this));
           register(new move(this));
           register(new decir(this));
           register(new Mirar(this));
           register(new Alias(this));
           register(new Unalias(this));
        }
        
        private void load_alias()
        {
           AddBasicAlias("n", "mover norte");
           AddBasicAlias("s", "mover sur");
           AddBasicAlias("e", "mover este");
           AddBasicAlias("o", "mover oeste");
           AddBasicAlias("ne", "mover noreste");
           AddBasicAlias("no", "mover noroeste");
           AddBasicAlias("se", "mover sureste");
           AddBasicAlias("so", "mover suroeste");
        }

        private void processLine(string line)
        {
           
           
            /* los comandos de movimiento se pueden acumular para ir "procesándose"
             * mientras que los comandos de ataque/etc se procesan instantáneamente... y se decide si se ejecutan o no...
             * Las habilidades tendrán un Global CD y un Individual CD cada una...
             * 
             */
            if (actualWiz != null)
            {//Estamos en un wizard. Pasar el control al WizardBase
                actualWiz.tratar(line);
            }else
            {
                //Tratamiento de Aliases
                line = ProcessAlias(line);	            
	            try {
	                execute(line);
	            }catch(MudException excpt)
	            {
	                render(excpt.Message);
	            }	            
            }
        }

        protected void ClientLoop()
        {
            try
            {
                //TODO: hacer + flexible
                String welcome = (new StreamReader(Directory.GetCurrentDirectory() + "\\Config\\docs\\login\\welcome.txt")).ReadToEnd();
                render(welcome);
                render("Introduce el correo:");
                string user = leerLinea();

                lock (objlock)
                {
                    if (user == null) { return; }
                    clientes.Add(this);
                    if (user.Length > 256)
                        user = user.Substring(0, 256);
                    user = Regex.Replace(user, "[ÿüûýúù][ÿüûýúù].", "");
                    actualWiz = new LoginWizard(this, "login", user);
                    actualWiz.tratar(user);
                }
                while (true)
                {
                    string line = leerLinea();
                    if (line == null) { break; }

                    lock (objlock)
                    {
                        if (line.Length > 256)
                            line = line.Substring(0, 256);

                        // No me gusta demasiado, demasiado bucle y demasiado rollo..., es para que el backspace borre un caracter en vez de ser \b
                        while (line.Contains('\b' + ""))
                        {
                            int index = line.IndexOf('\b');
                            int tam = line.Length;
                            line = (index > 0 ? line.Substring(0, index - 1) : "") + (tam > index ? line.Substring(index + 1, tam - index - 1) : "");
                        }
                        // Control de Historial
                        if (line.StartsWith("."))
                        {
                            if (line.Length == 1 && historial.Count > 0)
                                line = historial[historial.Count - 1].ToString();
                            else if (line.Length > 1)
                            {
                                int count = -1;
                                if (Int32.TryParse(line.Substring(1, line.Length - 1), out count))
                                {
                                    if (historial.Count > count)
                                    {
                                        line = historial[count].ToString();
                                    }
                                }
                            }
                        }
                        historial.Add(line);
                        // TODO: Procesar la línea introducida por teclado
                        processLine(line);
                        doprompt(prompt);
                    }
                }
            }
            catch (EndOfClientException eoc)
            {
                //TODO: Logearlo al pj no al general.
                Log.getInstance().info(eoc.Message.ToString() + " ha ordenado el fin del cliente");
            }
            catch (Exception xcpt)
            {
                Log.getInstance().error("Error en el bucle del cliente: " + xcpt.ToString());
            }
            finally
            {
                lock (objlock)
                {
                    Log.getInstance().info("Eliminando cliente[]");
                    clientes.Remove(this);
                    finbucle();                    
                }
            }
        }



        internal void Exit(String quien)
        {
            throw new EndOfClientException("Función Exit("+quien+")");
        }
    }
}
